package com.jieshao.service

import com.intellij.dvcs.repo.VcsRepositoryManager
import com.intellij.dvcs.repo.VcsRepositoryMappingListener
import com.intellij.notification.NotificationGroupManager
import com.intellij.notification.NotificationType
import com.intellij.openapi.components.Service
import com.intellij.openapi.components.service
import com.intellij.openapi.fileEditor.FileEditorManager
import com.intellij.openapi.ide.CopyPasteManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.guessProjectDir
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.wm.WindowManager
import com.jieshao.enhance.lineSelection
import com.jieshao.enhance.locateRemote
import com.jieshao.rule.Rule
import com.jieshao.rule.ScriptContext
import com.jieshao.script.evalString
import com.jieshao.setting.ApplicationSettings
import com.jieshao.setting.ProjectSettings
import com.jieshao.utils.LineShareBundle
import git4idea.repo.GitRepository
import git4idea.repo.GitRepositoryManager
import java.awt.datatransfer.StringSelection

@Service(Service.Level.PROJECT)
class LineShareRuntime(val project: Project) {

    var rule: Rule? = null

    var property: ScriptContext = ScriptContext()

    /**
     * 获取当前仓库和
     */
    fun detect(consumer: (Rule?) -> Unit) {
        val projectDirectory = project.guessProjectDir()
        if (projectDirectory == null) {
            consumer.invoke(null)
            return
        }

        property.projectPath = projectDirectory.path

        getRepositoryForFile(projectDirectory) { repository -> getPlatformForRepository(repository).let(consumer) }
    }

    private fun getPlatformForRepository(repository: GitRepository): Rule? {

        val settings = project.service<ProjectSettings>()

        val remote = repository.locateRemote(settings.remote) ?: return null

        property.origin = remote.firstUrl ?: return null

        property.currentRevision = repository.currentRevision?:""

        val applicationSettings = service<ApplicationSettings>()

        rule = applicationSettings.findRuleByCustomDomain(property.origin) ?: return null

        return rule
    }

    private fun getRepositoryForFile(projectDirectory: VirtualFile, consumer: (GitRepository) -> Unit) {
        val gitRepositoryManager = GitRepositoryManager.getInstance(project)
        val repository = gitRepositoryManager.getRepositoryForFile(projectDirectory)
        if (repository != null) {
            consumer.invoke(repository)
            return
        }

        val busConnection = project.messageBus.connect()
        busConnection
            .subscribe(
                VcsRepositoryManager.VCS_REPOSITORY_MAPPING_UPDATED,
                VcsRepositoryMappingListener {
                    busConnection.disconnect()
                    gitRepositoryManager.getRepositoryForFile(projectDirectory)?.let(consumer)
                }
            )
    }

    fun doProcess() {
        //渲染结果
        val res = render(rule!!.template)
        copy(res)
    }

    private fun render(template: String): String {
        return evalString(template, property)
    }

    fun isInLocalFileSystem(): Boolean {
        return FileEditorManager.getInstance(project).selectedTextEditor?.let { editor ->
            return editor.virtualFile.isInLocalFileSystem
        } ?: false
    }

    /**
     * 获取选择信息
     */
    fun getSelectInfo() {
        FileEditorManager.getInstance(project).selectedTextEditor?.let { editor ->
            property.isLocalFile = editor.virtualFile.isInLocalFileSystem
            if (property.isLocalFile) {
                property.filePath = editor.virtualFile.path.substring(property.projectPath.length)
            } else {
                property.filePath = editor.virtualFile.path
            }
            try {
                property.lineSelection = editor.lineSelection
            } catch (exception: Exception) {
                property.lineSelection = null
            }
        } ?: run {
            property.isLocalFile = false
            property.filePath = ""
            property.lineSelection = null
        }
    }

    /**
     * 状态栏显示
     * @see com.intellij.ide.actions.CopyReferenceUtil.setStatusBarText
     */
    private fun setStatusBarText(message: String) {
        project.let { WindowManager.getInstance().getStatusBar(it)?.setInfo(message) }
    }

    /**
     * 复制文本到剪贴板
     * @see com.intellij.ide.actions.CopyReferenceAction
     */
    private fun copy(url: String) {
        CopyPasteManager.getInstance().setContents(StringSelection(url))
        setStatusBarText(LineShareBundle.message("action.LineShare.CopyStatus", url))
    }

    fun notification(title: String, context: String) {
        NotificationGroupManager.getInstance().getNotificationGroup("line.share.notification.general")
            .createNotification(
                title,
                context,
                NotificationType.INFORMATION
            ).notify(project)
    }

}